#include "StdAfx.h"
#include "MyMesh.hh"
#include <queue>

MyMesh::MyMesh(void) : TriangularMesh()
{
	m_bGeoPlane = false;
	draw_org_data_ = false;
	add_property(EPropNewPoint);
	add_property(EPropNewPointFlag);
	add_property(FPropSplitTriangle);
	add_property(EPropCubeEdgeFlag);
	add_property(FPropCubeFace);
	add_property(VPropOrgPoint);
	add_property(VPropOrgNormal);
}

MyMesh::~MyMesh(void)
{
	remove_property(EPropNewPoint);
	remove_property(EPropNewPointFlag);
	remove_property(FPropSplitTriangle);
	remove_property(EPropCubeEdgeFlag);
	remove_property(FPropCubeFace);
	remove_property(VPropOrgPoint);
	remove_property(VPropOrgNormal);
}


void MyMesh::init()
{
	TriangularMesh::init();

	FaceIter f_it;

	for(f_it=faces_begin(); f_it!=faces_end(); ++f_it){
		property(FPropCubeFace, f_it) = kNone;
	}
}

bool MyMesh::create_boundary_path(OpenMesh::VertexHandle _start_vh, OpenMesh::VertexHandle _end_vh)
{
	Point p[3];
	OpenMesh::Vec3f dir;

	p[0] = Point(0.0f, 0.0f, 0.0f);
	p[1] = point(_start_vh);
	p[2] = point(_end_vh);

	PosGraph::Math::Vec3f temp_dir, temp_pos;

	dir = cross((p[1]-p[0]), (p[2]-p[0]));
	dir.normalize();

	temp_dir[0] = dir[0];
	temp_dir[1] = dir[1];
	temp_dir[2] = dir[2];

	temp_pos[0] = p[0][0];
	temp_pos[1] = p[0][1];
	temp_pos[2] = p[0][2];

	m_geo_plane.set(temp_dir, temp_pos);

	m_bGeoPlane = true;

	Point pnt[2], edge_pnt;
	HalfedgeHandle h_h;
	float dis[2];
	EdgeIter e_iter;
	vector<FaceHandle> split_faces;

	for(e_iter = edges_begin(); e_iter != edges_end(); ++e_iter){
		property(EPropNewPointFlag, e_iter) = false;
	}

	FaceIter f_iter;
	for(f_iter = faces_begin(); f_iter != faces_end(); ++f_iter){
		property(FPropSplitTriangle, f_iter) = false;
	}

	EdgeHandle end_eh;

	for(VertexOHalfedgeIter voh_it=voh_iter(_end_vh); voh_it; ++voh_it){
		h_h = next_halfedge_handle(voh_it);
		pnt[0] = point(to_vertex_handle(h_h));
		pnt[1] = point(from_vertex_handle(h_h));

		dis[0] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[0][0], pnt[0][1], pnt[0][2]));
		dis[1] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[1][0], pnt[1][1], pnt[1][2]));

		if(dis[0]*dis[1] <= 0.0){
			edge_pnt = (fabs(dis[0])*pnt[1]+fabs(dis[1])*pnt[0])/(fabs(dis[0])+fabs(dis[1]));
			if(dot(edge_pnt-point(_end_vh), point(_end_vh)-point(_start_vh)) < 0){
				property(EPropNewPoint, edge_handle(h_h)) = edge_pnt;
				property(EPropNewPointFlag, edge_handle(h_h)) = true;

				end_eh = edge_handle(h_h);

				if(property(FPropSplitTriangle, face_handle(h_h)) == false){
					property(FPropSplitTriangle, face_handle(h_h)) = true;
					split_faces.push_back(face_handle(h_h));
				}

				break;
			}
		}
	}

	
	for(VertexOHalfedgeIter voh_it=voh_iter(_start_vh); voh_it; ++voh_it){
		h_h = next_halfedge_handle(voh_it);
		pnt[0] = point(to_vertex_handle(h_h));
		pnt[1] = point(from_vertex_handle(h_h));

		dis[0] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[0][0], pnt[0][1], pnt[0][2]));
		dis[1] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[1][0], pnt[1][1], pnt[1][2]));

		if(dis[0]*dis[1] <= 0.0){
			edge_pnt = (fabs(dis[0])*pnt[1]+fabs(dis[1])*pnt[0])/(fabs(dis[0])+fabs(dis[1]));
			if(dot(edge_pnt-point(_start_vh), point(_end_vh)-point(_start_vh)) > 0){
				property(EPropNewPoint, edge_handle(h_h)) = edge_pnt;
				property(EPropNewPointFlag, edge_handle(h_h)) = true;
				
				if(property(FPropSplitTriangle, face_handle(h_h)) == false){
					property(FPropSplitTriangle, face_handle(h_h)) = true;
					split_faces.push_back(face_handle(h_h));
				}
				break;
			}
		}
	}


	while(1){
		for(FaceHalfedgeIter fh_it=fh_iter(face_handle(opposite_halfedge_handle(h_h))); fh_it; ++fh_it){
			if(edge_handle(fh_it) == edge_handle(h_h))
				continue;


			pnt[0] = point(to_vertex_handle(fh_it));
			pnt[1] = point(from_vertex_handle(fh_it));

			dis[0] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[0][0], pnt[0][1], pnt[0][2]));
			dis[1] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[1][0], pnt[1][1], pnt[1][2]));

			if(dis[0]*dis[1] <= 0.0){
				edge_pnt = (fabs(dis[0])*pnt[1]+fabs(dis[1])*pnt[0])/(fabs(dis[0])+fabs(dis[1]));
				
				if(dot(edge_pnt-point(_start_vh), point(_end_vh)-point(_start_vh)) > 0){
					property(EPropNewPoint, edge_handle(fh_it)) = edge_pnt;
					property(EPropNewPointFlag, edge_handle(fh_it)) = true;
		
					h_h = (HalfedgeHandle) fh_it;
					if(property(FPropSplitTriangle, face_handle(h_h)) == false){
						property(FPropSplitTriangle, face_handle(h_h)) = true;
						split_faces.push_back(face_handle(h_h));
					}
				break;
				}
			}
		}

		if(edge_handle(h_h) == end_eh)
			break;
		
	}

   
	/*EdgeIter e_it;
	for(e_it = edges_begin(); e_it != edges_end(); ++e_it){
		if(property(EPropNewPointFlag, e_it)){
			split_edge(e_it);
		}
	}*/

	for(int i = 0; i < split_faces.size(); i++){
		split_face(split_faces[i]);
	}

	return true;
}

void MyMesh::draw()
{
	//TriangularMesh::draw();

	FaceIter f_it;
	EdgeIter e_it;
	/*Point pnt[2], edge_pnt[2];
	float dis[2];
	int cnt = 0;

	if(m_bGeoPlane == true){*/
		glPushAttrib(GL_CURRENT_BIT);
	//glColor3f(1.0, 0.0, 1.0);
		
	/*for(f_it = faces_begin(); f_it != faces_end(); ++f_it){
		cnt = 0;
		for (FaceHalfedgeIter fh_it=fh_iter(f_it); fh_it; ++fh_it){

			if(property(EPropNewPointFlag, edge_handle(fh_it)) == false)
				continue;

			pnt[0] = point(to_vertex_handle(fh_it));
			pnt[1] = point(from_vertex_handle(fh_it));

			dis[0] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[0][0], pnt[0][1], pnt[0][2]));
			dis[1] = m_geo_plane.calcSignedDistance(PosGraph::Math::Vec3f(pnt[1][0], pnt[1][1], pnt[1][2]));

			if(dis[0]*dis[1] <= 0.0){
				edge_pnt[cnt] = (fabs(dis[0])*pnt[1]+fabs(dis[1])*pnt[0])/(fabs(dis[0])+fabs(dis[1]));
				cnt++;
			}
		}

		if(cnt == 2){
			glBegin(GL_LINES);
			glVertex3fv(edge_pnt[0]);
			glVertex3fv(edge_pnt[1]);
			glEnd();
		}
	}*/

	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(1.0, 1.0);

	for(f_it = faces_begin(); f_it != faces_end(); ++f_it){
		//if(valence(f_it) > 3 ){
		if(property(FPropCubeFace, f_it) == kNY){
			glColor3f(0.0, 0.0, 1.0);
		}
		else if(property(FPropCubeFace, f_it) == kPY){
			glColor3f(1.0, 0.0, 0.0);
		}
		else if(property(FPropCubeFace, f_it) == kPX){
			glColor3f(0.0, 1.0, 0.0);
		}
		else if(property(FPropCubeFace, f_it) == kNX){
			glColor3f(0.0, 1.0, 1.0);
		}
		else if(property(FPropCubeFace, f_it) == kPZ){
			glColor3f(1.0, 1.0, 0.0);
		}
		else if(property(FPropCubeFace, f_it) == kNZ){
			glColor3f(1.0, 0.0, 1.0);
		}
		else{
			glColor3f(1.0, 1.0, 1.0);
			//continue;
		}
	
			glBegin(GL_POLYGON);
			for(FaceVertexIter fv_it = fv_iter(f_it); fv_it; ++fv_it){
				if(!draw_org_data_)
					glVertex3fv(point(fv_it));
				else
					glVertex3fv(property(VPropOrgPoint, fv_it));
			}
			glEnd();
		

	}
	glDisable(GL_POLYGON_OFFSET_FILL);
	
	glBegin(GL_LINES);
	for(e_it = edges_begin(); e_it != edges_end(); ++e_it){
		if(property(EPropCubeEdgeFlag, e_it) == false){
			glColor3f(0.0, 0.0, 0.0);
			//glLineWidth(1);
		}
		else{
			glColor3f(0.0, 0.0, 0.0);
			//glLineWidth(2);
		}
	
		if(!draw_org_data_){
			glVertex3fv(point(to_vertex_handle(halfedge_handle(e_it, 0))));
			glVertex3fv(point(to_vertex_handle(halfedge_handle(e_it, 1))));
		}
		else{
			glVertex3fv(property(VPropOrgPoint, to_vertex_handle(halfedge_handle(e_it, 0))));
			glVertex3fv(property(VPropOrgPoint, to_vertex_handle(halfedge_handle(e_it, 1))));
		}
	}
	glEnd();

	
	/*glDisable(GL_DEPTH_TEST);
	glColor3f(0.0, 1.0, 0.0);
	glBegin(GL_POINTS);
	for(e_it = edges_begin(); e_it != edges_end(); ++e_it){
		if(property(EPropNewPointFlag, e_it)){
			glVertex3fv(property(EPropNewPoint, e_it));
			
		}
	}
	 glVertex3f(1.0/sqrt(2.0), 1.0/sqrt(2.0), 0.0);
	 glVertex3f(0.0, 1.0/sqrt(2.0), 1.0/sqrt(2.0));
	 glVertex3f(-1.0/sqrt(2.0), 1.0/sqrt(2.0), 0.0);
	 glVertex3f(0.0, 1.0/sqrt(2.0), -1.0/sqrt(2.0));
	 glVertex3f(1.0/sqrt(2.0), -1.0/sqrt(2.0), 0.0);
	 glVertex3f(0.0, -1.0/sqrt(2.0), 1.0/sqrt(2.0));
	 glVertex3f(-1.0/sqrt(2.0), -1.0/sqrt(2.0), 0.0);
	 glVertex3f(0.0, -1.0/sqrt(2.0), -1.0/sqrt(2.0));
	glEnd();
	glEnable(GL_DEPTH_TEST);*/

	glPopAttrib();
	//}
}

bool MyMesh::get_shortest_path(const VertexHandle _start_vh, const VertexHandle _end_vh, std::vector<HalfedgeHandle> &path)
 {
	OpenMesh::EPropHandleT<float> EPropLength;
    OpenMesh::VPropHandleT<HalfedgeHandle> VPropHHandle;
	OpenMesh::VPropHandleT<float> VPropPriority;
	OpenMesh::VPropHandleT<bool> VPropAuxFlag;
	OpenMesh::VPropHandleT<bool> VPropInQueue;

	
	 add_property(VPropPriority);
	 add_property(EPropLength);
	 add_property(VPropHHandle);
	 add_property(VPropAuxFlag);
	 add_property(VPropInQueue);

	 EdgeIter e_it;
	 VertexIter	  v_it;
     Point           pnt[2];
	 float max_len = 0.0f, len;

	 std::priority_queue<VertexPriority> pq;

	 for(e_it=edges_begin(); e_it != edges_end(); ++e_it){
	    pnt[0] = point( to_vertex_handle(halfedge_handle(e_it, 0)));
        pnt[1] = point( to_vertex_handle(halfedge_handle(e_it, 1)));

		len = (pnt[0]-pnt[1]).length();

		property(EPropLength, e_it) = len;

		max_len += len;
	 }

	 for(v_it=vertices_begin(); v_it != vertices_end(); ++v_it){
		 property(VPropPriority, v_it) = max_len;
		 property(VPropAuxFlag, v_it) = false;
		 property(VPropInQueue, v_it) = false;
	 }

	 property(VPropPriority, _start_vh) = 0.0f;

	 VertexPriority pr;
	 pr.priority = 0.0f;
	 pr.vh_ = _start_vh;

	 VertexHandle _vh, _nvh;

	 property(VPropInQueue, _start_vh) = true;

	   //CString str;
		

	 pq.push(pr);

	   //str.Format(_T("push [%d] : %f\n"), _start_vh.idx(), property(VPropPriority, _start_vh));

		//OutputDebugString(str);

	 while(!pq.empty()){

		do{
	       pr = pq.top();
		   pq.pop();
		   _vh = pr.vh_;

		  //str.Format(_T("pop [%d] : %f\n"), _vh.idx(), property(VPropPriority, _vh));

		//OutputDebugString(str);

		}while(property(VPropInQueue, _vh) == false);

		property(VPropInQueue, _vh) = false;

		property(VPropAuxFlag, _vh) = true;

		if(_vh == _end_vh)
			break;


			VertexOHalfedgeIter vohe_it;

			for(vohe_it=voh_iter(_vh); vohe_it; ++vohe_it){
				_nvh = to_vertex_handle(vohe_it);

				len = property(EPropLength, edge_handle(vohe_it));

				if(property(VPropAuxFlag, _nvh))
					continue;

				if(property(EPropCubeEdgeFlag, edge_handle(vohe_it)) == true)
					continue;

				if(property(FPropCubeFace, face_handle(vohe_it)) != kNone && property(FPropCubeFace, face_handle(opposite_halfedge_handle(vohe_it))) != kNone)
					continue;

				if(property(VPropInQueue, _nvh) && property(VPropPriority, _nvh) > property(VPropPriority, _vh) + len){
					property(VPropInQueue, _nvh) = false;
				}

				if( !property(VPropInQueue, _nvh) ){
					property(VPropPriority, _nvh) = property(VPropPriority, _vh) + len;
					property(VPropHHandle, _nvh) = vohe_it;

					property(VPropInQueue, _nvh) = true;

					pr.priority = property(VPropPriority, _vh) + len;
					pr.vh_ = _nvh;
					pq.push(pr);

					//str.Format(_T("push [%d] : %f\n"), _nvh.idx(), property(VPropPriority, _nvh));

					//OutputDebugString(str);
				}
			}
	 }

	 path.clear();

	_vh = _end_vh;
	HalfedgeHandle _he;
	bool is_path_valid = true;

	do{
		_he = property(VPropHHandle, _vh);

		if(_he.is_valid() == false){
			is_path_valid = false;
			path.clear();
			break;
		}

		_vh = from_vertex_handle(_he);
		path.insert(path.begin(), _he);
		property(EPropCubeEdgeFlag, edge_handle(_he)) = true;

	}while(_vh != _start_vh);

 	 remove_property(VPropPriority);
	 remove_property(EPropLength);
	 remove_property(VPropHHandle);
	 remove_property(VPropAuxFlag);
	 remove_property(VPropInQueue);

	return is_path_valid;
 }

 void MyMesh::map_onto_cube_face(std::vector<HalfedgeHandle> &edge_path0, std::vector<HalfedgeHandle> &edge_path1, std::vector<HalfedgeHandle> &edge_path2, std::vector<HalfedgeHandle> &edge_path3, CubeFace _whichface)
 {
	OpenMesh::FPropHandleT<float> FPropAuxFlag;

	std::vector<HalfedgeHandle> *edge_paths[4];
	std::queue<FaceHandle> pq;

	edge_paths[0] = &edge_path0;
	edge_paths[1] = &edge_path1;
	edge_paths[2] = &edge_path2;
	edge_paths[3] = &edge_path3;

	add_property(FPropAuxFlag);

	FaceIter f_it;
	FaceHandle fh;

	for(f_it=faces_begin(); f_it!=faces_end(); ++f_it){
		property(FPropAuxFlag, f_it) = false;
	}

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < edge_paths[i]->size(); k++){
			fh = face_handle(edge_paths[i]->at(k));


			if(property(FPropAuxFlag, fh) == false){
				pq.push(fh);
				property(FPropAuxFlag, fh) = true;
				property(FPropCubeFace, fh) = _whichface;
			}

			property(FPropAuxFlag, face_handle(opposite_halfedge_handle(edge_paths[i]->at(k)))) = true;
		}
	}

	while(pq.empty()==false){
		fh = pq.front();
		pq.pop();	

		for(FaceHalfedgeIter fh_it=fh_iter(fh); fh_it; ++fh_it){
			FaceHandle fh2 = face_handle(opposite_halfedge_handle(fh_it));
			if(property(FPropAuxFlag, fh2))
				continue;

			pq.push(fh2);
			property(FPropAuxFlag, fh2) = true;
			property(FPropCubeFace, fh2) = _whichface;
		}
	}

	remove_property(FPropAuxFlag);
   
 }

 void MyMesh::automatic_selection(std::vector<VertexHandle> &selected_vertices)
 {
	 VertexIter v_it;
	 Point      p;
	 Point      points[8];
	 VertexHandle near_vertices[8];
	 int i;

	 float dist[8] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, len;

	 points[3] = Point(1.0/sqrt(2.0), 1.0/sqrt(2.0), 0.0);
	 points[2] = Point(0.0, 1.0/sqrt(2.0), 1.0/sqrt(2.0));
	 points[1] = Point(-1.0/sqrt(2.0), 1.0/sqrt(2.0), 0.0);
	 points[0] = Point(0.0, 1.0/sqrt(2.0), -1.0/sqrt(2.0));
	 points[7] = Point(1.0/sqrt(2.0), -1.0/sqrt(2.0), 0.0);
	 points[6] = Point(0.0, -1.0/sqrt(2.0), 1.0/sqrt(2.0));
	 points[5] = Point(-1.0/sqrt(2.0), -1.0/sqrt(2.0), 0.0);
	 points[4] = Point(0.0, -1.0/sqrt(2.0), -1.0/sqrt(2.0));
	 
	 selected_vertices.resize(8);

	 for(v_it=vertices_begin(); v_it!=vertices_end(); v_it++){
		 p = point(v_it);

		 for(i = 0; i < 8; i++){
			 len = (p-points[i]).length();

			 if(dist[i] > len){
				 dist[i] = len;
				 selected_vertices[i] = v_it;
			 }
		 }
	 }
 }

 void MyMesh::map_onto_cube(std::vector<VertexHandle> &selected_vertices)
 {
	 std::vector<HalfedgeHandle> cube_edge_path[12];
	 std::vector<HalfedgeHandle> cube_edge_path_reverse[12];
	 int i;
	 EdgeIter e_it;

	 for(e_it=edges_begin(); e_it!=edges_end(); ++e_it){
		 property(EPropCubeEdgeFlag, e_it) = false;
	 }

	 for(i = 0; i < 4; i++)
		get_shortest_path(selected_vertices[i], selected_vertices[(i+1)%4], cube_edge_path[i]);
	 for(i = 0; i < 4; i++)
		get_shortest_path(selected_vertices[i+4], selected_vertices[(i+1)%4+4], cube_edge_path[i+4]);

	 for(i = 0; i < 8; i++){
		 for(int k = cube_edge_path[i].size()-1; k >= 0; k--)
			 cube_edge_path_reverse[i].push_back(opposite_halfedge_handle(cube_edge_path[i][k]));
	 }

	 map_onto_cube_face(cube_edge_path[0], cube_edge_path[1], cube_edge_path[2], cube_edge_path[3], kPY); 
	 map_onto_cube_face(cube_edge_path_reverse[7], cube_edge_path_reverse[6], cube_edge_path_reverse[5], cube_edge_path_reverse[4], kNY);
	 
	 
	for(i = 0; i < 4; i++)
		get_shortest_path(selected_vertices[i], selected_vertices[i+4], cube_edge_path[i+8]);

	 for(i = 0; i < 4; i++){
		 for(int k = cube_edge_path[i+8].size()-1; k >= 0; k--)
			 cube_edge_path_reverse[i+8].push_back(opposite_halfedge_handle(cube_edge_path[i+8][k]));
	 }

	  for(i = 0; i < 4; i++)
		map_onto_cube_face(cube_edge_path[i+4], cube_edge_path_reverse[(i+1)%4+8], cube_edge_path_reverse[i], cube_edge_path[i+8], (CubeFace) (i+2)); // kPZ = 2, kPX = 3, kNZ = 4, kNX = 5
	
 }

 void trimString( std::string& _string) {
  // Trim Both leading and trailing spaces

  size_t start = _string.find_first_not_of(" \t\r\n");
  size_t end   = _string.find_last_not_of(" \t\r\n");

  if(( std::string::npos == start ) || ( std::string::npos == end))
    _string = "";
  else
    _string = _string.substr( start, end-start+1 );
}


 bool MyMesh::load_org_data(const std::string &strFilename) 
 {

	 std::fstream _in( strFilename.c_str(), std::ios_base::in );


  std::string line;
  std::string keyWrd;

  float                  x, y, z, u, v;

  std::vector<Point>     normals;
 
  std::string            matname;

  VertexIter viter1 = vertices_begin();
  VertexIter viter2 = vertices_begin();

  while( _in && !_in.eof() )
  {
    std::getline(_in,line);
    if ( _in.bad() ){
      omerr() << "  Warning! Could not read file properly!\n";
      return false;
    }

    // Trim Both leading and trailing spaces
    trimString(line);

    // comment
    if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
      continue;
    }

    std::stringstream stream(line);

    stream >> keyWrd;

    // vertex
    if (keyWrd == "v")
    {
      stream >> x; stream >> y; stream >> z;

	  if ( !stream.fail() ){
       	property(VPropOrgPoint, viter1) = Point(x, y, z);
		++viter1;
	  }
    }

      // normal
    else if (keyWrd == "vn")
    {
      stream >> x; stream >> y; stream >> z;

      if ( !stream.fail() ){
        property(VPropOrgNormal, viter2) = Point(x, y, z);
		++viter2;
      }
    }

  }

  draw_org_data_ = true;

  return true;
 }

 bool MyMesh::save(const std::string &strFilename) 
 {
	 FILE    *fp, *fp2;

	 fp = fopen(strFilename.c_str(), "w");

	 char str[100];

	 sprintf(str, "%s.tag", strFilename.c_str());

	 fp2 = fopen(str, "w");

	 if(fp == NULL || fp2 == NULL)
		 return false;

	 VertexIter v_it;
	 Point      p;

	 for(v_it=vertices_begin(); v_it!=vertices_end(); ++v_it){
		 p = point(v_it);
		fprintf(fp, "v %f %f %f\n", p[0], p[1], p[2]);    
	 }

	 fprintf(fp2, "%d\n", n_faces());
	 FaceIter f_it;
	 std::vector<FaceHandle> cube_map[6];

	 for(f_it=faces_begin(); f_it!=faces_end(); ++f_it){
		 cube_map[(int)(property(FPropCubeFace, f_it))].push_back(f_it);
		 
		 fprintf(fp2, "%d\n", (int)(property(FPropCubeFace, f_it)));
	 }

	 FaceHandle fh;
	 FaceVertexIter  fv_it;

	 for(int i = 0; i < 6; i++){
		 if(i == kPY){
			 fprintf(fp, "usemtl py\n");
		 }
		 else if(i == kNY){
			 fprintf(fp, "usemtl ny\n");
		 }
		 else if(i == kPZ){
			 fprintf(fp, "usemtl pz\n");
		 }
		 else if(i == kPX){
			 fprintf(fp, "usemtl px\n");
		 }
		 else if(i == kNZ){
			 fprintf(fp, "usemtl nz\n");
		 }
		 else if(i == kNX){
			 fprintf(fp, "usemtl nx\n");
		 }
		 for(int k = 0; k < cube_map[i].size(); k++){
			 fh = cube_map[i].at(k);
			 fprintf(fp, "f");
			 for (fv_it=fv_iter(fh); fv_it; ++fv_it)
			{
				fprintf(fp, " %d", 1+fv_it.handle().idx());
			}
			fprintf(fp, "\n");
		}
	 }

	 fclose(fp);
	 fclose(fp2);

	 return true;
 }